/**
 * @copyright Copyright (c) 2007-2024, Guangzhou Xaircraft Technology Co., Ltd.
 */

#ifndef MODULES_DEAMON_COMMON_H_      // NOLINT
#define MODULES_DEAMON_COMMON_H_

#include <string>
#include <list>
#include <map>
#include <stdint.h>  // NOLINT
#include <memory>
#include <unistd.h>  // NOLINT

// #include "system/system_modules.h"

namespace xag {
  namespace xos {  // NOLINT
    namespace deamon {  // NOLINT

      constexpr char KEYWORDS[] = "xag_";

#if 1
#define PKG_NAME "PowerCtl"
      const std::string SWITCH_CONFIG_PATH =
          "/usr/app/config/" + std::string(PKG_NAME) + "/deamon_switch.conf";

      const std::string MONITOR_REPORT_CONFIG_PATH =
          "/usr/app/config/" + std::string(PKG_NAME) + "/monitor_report.conf";
#endif

/* Files */
#define STAT "/proc/stat"
#define UPTIME "/proc/uptime"
#define DISKSTATS "/proc/diskstats"
#define INTERRUPTS "/proc/interrupts"
#define MEMINFO "/proc/meminfo"
#define SYSFS_BLOCK "/sys/block"
#define SYSFS_DEV_BLOCK "/sys/dev/block"
#define SYSFS_DEVCPU "/sys/devices/system/cpu"
#define SYSFS_TIME_IN_STATE "cpufreq/stats/time_in_state"
#define S_STAT "stat"
#define DEVMAP_DIR "/dev/mapper"
#define DEVICES "/proc/devices"
#define SYSFS_USBDEV "/sys/bus/usb/devices"
#define DEV_DISK_BY "/dev/disk/by"
#define SYSFS_IDVENDOR "idVendor"
#define SYSFS_IDPRODUCT "idProduct"
#define SYSFS_BMAXPOWER "bMaxPower"
#define SYSFS_MANUFACTURER "manufacturer"
#define SYSFS_PRODUCT "product"
#define SYSFS_FCHOST "/sys/class/fc_host"

#define PRE ""
#define PROC "/proc"

#define PID_STAT PRE "/proc/%u/stat"
#define PID_STATUS PRE "/proc/%u/status"
#define PID_IO PRE "/proc/%u/io"
#define PID_CMDLINE PRE "/proc/%u/cmdline"
#define PID_SMAP PRE "/proc/%u/smaps"
#define PID_FD PRE "/proc/%u/fd"
#define PID_SCHED PRE "/proc/%u/schedstat"

#define PROC_TASK PRE "/proc/%u/task"
#define TASK_STAT PRE "/proc/%u/task/%u/stat"
#define TASK_SCHED PRE "/proc/%u/task/%u/schedstat"
#define TASK_STATUS PRE "/proc/%u/task/%u/status"
#define TASK_IO PRE "/proc/%u/task/%u/io"
#define TASK_CMDLINE PRE "/proc/%u/task/%u/cmdline"
#define TASK_SMAP PRE "/proc/%u/task/%u/smaps"
#define TASK_FD PRE "/proc/%u/task/%u/fd"

#define F_NO_PID_IO 0x01
#define NO_PID_IO(m) (((m) & F_NO_PID_IO) == F_NO_PID_IO)

/* Define SP_VALUE() to normalize to % */
#define SP_VALUE(m, n, p) (((double)((n) - (m))) / (p) * 100.0)  // NOLINT
#define S_VALUE(m, n, p) (((double)((n) - (m))) / (p) * 100.0)  // NOLINT

      struct pid_stats {  // NOLINT
        uint64_t read_bytes __attribute__((aligned(8)));
        uint64_t write_bytes __attribute__((packed));
        uint64_t cancelled_write_bytes __attribute__((packed));
        uint64_t utime __attribute__((packed));
        uint64_t stime __attribute__((packed));
        uint64_t gtime __attribute__((packed));
        uint64_t wtime __attribute__((packed));
        unsigned long nvcsw __attribute__((packed));  // NOLINT
        unsigned long nivcsw __attribute__((packed));  // NOLINT
        uint32_t threads __attribute__((packed));
        uint32_t fd_nr __attribute__((packed));
      };

      struct ProgramState {  // NOLINT
        std::string name;         // 程序名字
        pid_t pid;                // 程序的 pid
        double cpu;               // 程序 cpu 使用占比
        double user_cpu;          // 程序 用户态cpu 使用占比
        double system_cpu;        // 程序 内核态cpu 使用占比
        uint32_t total_memory;    // 程序总内存
        uint32_t physical_memory;  // 程序使用物理内存
        uint32_t shared_memory;   // 程序使用共享内存
        uint32_t thread_num;      // 线程数
        double nvcsw;             // 程序自愿上下文切换
        double nivcsw;            // 程序非自愿上下文切换
        double rbytes;            // 进程IO读速度KB/S
        double wbytes;            // 进程IO写速度KB/S
        double cbytes;            // 进程写入磁盘被取消的数据大小速度KB/S
      };

#define PID_STATS_SIZE (sizeof(struct pid_stats))

      struct st_pid {  // NOLINT
        pid_t pid;
        uid_t uid;
        bool exist = false; /* TRUE if PID exists */
        uint32_t flags = 0;
        std::unique_ptr<pid_stats> pstats[2];
        pid_t tgid;

        std::map<pid_t, st_pid> sub_thread_map;
        std::string name;
      };

      struct MemoryInformation {  // NOLINT
        unsigned long total_memory;  // NOLINT
        unsigned long physical_memory;  // NOLINT
        unsigned long shared_memory;  // NOLINT
      };

      class Common {  // NOLINT
      public:  // NOLINT
#define MAX_NAME_LEN 128
#define KB_TO_PG(k) ((k) >> Common::kb_shift)
#define PG_TO_KB(k) ((k) << Common::kb_shift)

        static void read_uptime(uint64_t *uptime);
        static void get_kb_shift(void);
        static void get_HZ(void);
        static uint64_t get_interval(uint64_t prev_uptime,
                                     uint64_t curr_uptime);

        static void add(pid_stats *a, pid_stats *b);
        static void get_st_pid(st_pid *a, const st_pid *b);
        static void get_st_pid(st_pid *a, int32_t a_idx, const st_pid *b, int32_t b_idx);
        static void display_info(struct st_pid *plist, int prev, int curr, uint64_t itv);
        static ProgramState get_program_state(st_pid *plist,
                                              int prev,
                                              int curr,
                                              uint64_t itv);
        static void get_cpu_num(void);

      public:  // NOLINT
        static inline uint32_t kb_shift;
        static inline unsigned long SYS_HZ;  // NOLINT
        static inline unsigned long page_size;  // NOLINT
        static inline uint32_t sys_cpu_num = 4;
      };

    }  // namespace deamon
  }  // namespace xos
}   // namespace xag

#endif  // NOLINT
